package com.youlu.campus.service.item;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;

import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.ItemQueryReq;
import com.youlu.campus.entity.VO.res.ActivityCultureCreativeResponse;
import com.youlu.campus.entity.VO.res.MyBadgeRuleResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ItemInfoService {

    @Autowired
    private ActivityBadgeRuleService activityBadgeRuleService;

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserLikeItemService userLikeItemService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Lazy
    @Autowired
    private ActivityCultureCreativeConfigService activityCultureCreativeConfigService;

    private String ITEM_FEED_PRE_KEY = "com.luyou.item.feed.type:%s";

    private String QQ_MINI_LINKER = "/pages/cultural/cultural-detail?id=%s";

    public ActivityCultureCreativeResponse detailCultureCreative(String appId, String platform, String id, String userId) {
        ItemInfo itemInfo = this.detail(id);
        if (Objects.isNull(itemInfo)) {
            throw new BusinessException("未找到该文创商品");
        }
        ActivityCultureCreativeResponse cultureCreative = new ActivityCultureCreativeResponse();
        cultureCreative.setId(itemInfo.getId());
        cultureCreative.setDetail(itemInfo.getDetail());
        cultureCreative.setPrice(itemInfo.getPrice());
        cultureCreative.setTitle(itemInfo.getTitle());
        cultureCreative.setItemImageUrlList(itemInfo.getImageUrls());
        cultureCreative.setLike(itemInfo.getLike());
        cultureCreative.setSubTitle(itemInfo.getSubTitle());
        boolean liked = this.likedItem(appId, platform, userId, id);
        this.increHits(itemInfo.getId(), 1L);
        cultureCreative.setFavorited(liked);
        return cultureCreative;
    }

    public List<MyBadgeRuleResponse> findByActivityId(String activityId,Integer badgeType) {
        List<ActivityBadgeRule> activityBadgeRuleList = activityBadgeRuleService.findByActivityId(activityId,badgeType);
        if (CollectionUtils.isEmpty(activityBadgeRuleList)) {
            throw new BusinessException("该活动未配置勋章");
        }
        return activityBadgeRuleList.stream().map(activityBadgeRule -> {
            String itemId = activityBadgeRule.getItemId();
            MyBadgeRuleResponse myBadgeRule = new MyBadgeRuleResponse();
            ItemInfo itemInfo = this.mongoTemplate.findById(itemId, ItemInfo.class);
            if (Objects.nonNull(itemInfo)) {
                myBadgeRule.setBadgeTitle(itemInfo.getTitle());
                List<String> imageUrls = itemInfo.getImageUrls();
                if (CollectionUtils.isNotEmpty(imageUrls)) {
                    myBadgeRule.setBadgeImageUrl(imageUrls.get(0));
                    if (imageUrls.size() >= 3) {
                        myBadgeRule.setBadgeUnLockImageUrl(imageUrls.get(1));
                        myBadgeRule.setBadgeLockImageUrl(imageUrls.get(2));
                    }
                }
            }
            myBadgeRule.setId(itemId);
            myBadgeRule.setPriority(activityBadgeRule.getPriority());
            myBadgeRule.setRewardValue(activityBadgeRule.getRewardValue());
            return myBadgeRule;
        }).collect(Collectors.toList()).stream().sorted(Comparator.comparing(MyBadgeRuleResponse::getPriority)).collect(Collectors.toList());
    }


    public ItemInfo detail(String id) {
        return this.mongoTemplate.findById(id, ItemInfo.class);
    }

    public Page<ItemInfo> list(ItemQueryReq itemQueryReq) {
        Query query = new Query();
        if (StringUtils.isNotBlank(itemQueryReq.getTitle())) {
            Pattern pattern = Pattern.compile("^.*" + itemQueryReq.getTitle() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("title").regex(pattern));
        }
        if (Objects.nonNull(itemQueryReq.getItemType())) {
            query.addCriteria(Criteria.where("itemType").is(itemQueryReq.getItemType()));
        }
        if (Objects.nonNull(itemQueryReq.getOnSale())) {
            query.addCriteria(Criteria.where("onSale").is(itemQueryReq.getOnSale()));
        }
        if (StringUtils.isNotBlank(itemQueryReq.getCategory())) {
            query.addCriteria(Criteria.where("category").is(itemQueryReq.getCategory()));
        }
        PageRequest pageRequest = PageRequest.of(itemQueryReq.getPageNo() - 1, itemQueryReq.getPageSize());
        long count = this.mongoTemplate.count(query, ItemInfo.class);
        if (count == 0) {
            return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> count);
        }
        query.with(Sort.by(Sort.Direction.DESC, "createdTime"));
        List<ItemInfo> list = this.mongoTemplate.find(query.with(pageRequest), ItemInfo.class);
        if (!CollectionUtils.isEmpty(list)) {
            for (ItemInfo itemInfo : list) {
                itemInfo.setMiniQqLinker(String.format(QQ_MINI_LINKER, itemInfo.getId()));
            }
        }
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }


    public void saveOrUpdate(ItemInfo saveItemInfo) {
        Date now = new Date();
        if (StringUtils.isBlank(saveItemInfo.getId())) {
            saveItemInfo.setCreatedTime(now);
        }
        saveItemInfo.setUpdatedTime(now);
        if (CollectionUtils.isNotEmpty(saveItemInfo.getImageUrls())) {
            saveItemInfo.setImageUrl(saveItemInfo.getImageUrls().get(0));
        }
        this.mongoTemplate.save(saveItemInfo);
        activityBadgeRuleService.updateByItemId(saveItemInfo);
        activityCultureCreativeConfigService.doOnSaleByItemId(saveItemInfo.getId(),saveItemInfo.getOnSale());

    }

    public boolean likeItem(String appId, String platform, String userId,
                            String itemId) {
        boolean is = this.likedItem(appId, platform, userId,
                itemId);
        if (is) {
            return true;
        }
        UserLikeItem req = new UserLikeItem();
        req.setId(null);
        req.setAppId(appId);
        req.setItemId(itemId);
        req.setUserId(userId);
        req.setPlatform(platform);
        increLike(itemId, 1);
        return userLikeItemService.create(req);
    }

    public boolean unLikeItem(String appId, String platform, String userId,
                              String itemId) {
        UserLikeItem req = userLikeItemService.find(appId, platform, userId, itemId);
        if (Objects.isNull(req)) {
            return true;
        }
        decreLike(itemId, 1);
        return userLikeItemService.delete(req.getId());
    }

    public boolean likedItem(String appId, String platform, String userId,
                             String itemId) {
        UserLikeItem item = userLikeItemService.find(appId, platform, userId, itemId);
        if (Objects.isNull(item)) {
            return false;
        }
        return true;
    }

    public boolean increLike(String itemId, Integer like) {
        Query query = new Query().addCriteria(Criteria.where("id").is(itemId));
        Update update = new Update();
        update.inc("like", like);
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ItemInfo.class);
        this.updateActivityCultureLike(itemId);
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    public boolean decreLike(String itemId, Integer like) {
        ItemInfo itemInfo = this.detail(itemId);
        if (Objects.nonNull(itemInfo.getLike()) && itemInfo.getLike() > 0) {
            this.updateActivityCultureLike(itemId);
            return increLike(itemId, -like);
        }
        return true;
    }

    /**
     * 累加浏览量
     *
     * @param itemId
     * @param hits
     * @return
     */
    @Async
    public void increHits(String itemId, Long hits) {
        Query query = new Query().addCriteria(Criteria.where("id").is(itemId));
        Update update = new Update();
        update.inc("hits", hits);
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ItemInfo.class);
    }

    /**
     * 累加购买量
     *
     * @param itemId
     * @param amount
     * @return
     */
    @Async
    public void increaMount(String itemId, Long amount) {
        Query query = new Query().addCriteria(Criteria.where("id").is(itemId));
        Update update = new Update();
        update.inc("amount", amount);
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ItemInfo.class);
    }

    /**
     * 累加退款数量
     *
     * @param itemId
     * @param refundNum
     * @return
     */
    @Async
    public void increaRefundNum(String itemId, Long refundNum) {
        Query query = new Query().addCriteria(Criteria.where("id").is(itemId));
        Update update = new Update();
        update.inc("refundNum", refundNum);
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ItemInfo.class);
    }

    public List<ActivityFeedInfo> getFeedInfo(String bizType, Integer page) {
        String key = String.format(ITEM_FEED_PRE_KEY, bizType);
        try {
            List<String> s = redisTemplate.opsForList().range(key, 0, 10);
            if (Objects.isNull(s)) {
                return new ArrayList<>();
            }
            List<ActivityFeedInfo> data = new ArrayList<>();
            for (String ss : s) {
                ActivityFeedInfo a = JSON.parseObject(ss, ActivityFeedInfo.class);
                if (Objects.nonNull(a)) {
                    data.add(a);
                }
            }
            log.info(":>>> 商品:{},类型:{}, Feed流数据大小:{}", bizType, data == null ? 0 : data.size());
            return data;
        } catch (Exception e) {
            log.error(":>>> 获取Feed流错误:{}", e);
            return new ArrayList<>();
        }

    }

    public void addItemFeedInfo(String bizType, ActivityFeedInfo req) {
        if (StringUtils.isBlank(bizType)) {
            return;
        }
        String key = String.format(ITEM_FEED_PRE_KEY, bizType);
        Long size = redisTemplate.opsForList().size(key);
        log.info(":>>> 添加Feed之前特别注意Feed流长度大小:{}", size);
        if (Objects.isNull(size)) {
            redisTemplate.opsForList().leftPush(key, JSON.toJSONString(req));
            return;
        }
        if (size.compareTo(50L) == -1) {
            redisTemplate.opsForList().rightPush(key, JSON.toJSONString(req));
            log.info(":>>> 添加Feed之后<50,特别注意Feed流长度大小:{}", redisTemplate.opsForList().size(key));
            return;
        }
        redisTemplate.opsForList().rightPop(key);
        redisTemplate.opsForList().leftPush(key, JSON.toJSONString(req));
        log.info(":>>> 添加Feed之后>50,特别注意Feed流长度大小:{}", redisTemplate.opsForList().size(key));
    }

    /**
     * 更新活动文创商品人气值
     *
     * @param itemInfoId
     */
    @Async
    public void updateActivityCultureLike(String itemInfoId) {
        try {
            ItemInfo itemInfo = this.detail(itemInfoId);
            if (Objects.isNull(itemInfo)) {
                return;
            }
            Query query = new Query().addCriteria(Criteria.where("itemInfoId").is(itemInfoId));
            Update update = new Update();
            update.set("like", itemInfo.getLike());
            update.set("updatedTime", new Date());
            mongoTemplate.updateMulti(query, update, ActivityCultureCreativeConfig.class);
        } catch (Exception e) {
            log.error(":>>> 更新文创商品人气值错误:{}", e);
        }


    }

}
